import { TComponent } from '@material/typeing';
import { usePropsValue } from '@material/hooks';
import {
    ForwardRefRenderFunction,
    forwardRef,
    useEffect,
    useImperativeHandle,
    useRef
} from 'react';

import { clsx } from 'react-runtime-clsx';

import $style from './index.scss';
export interface TextAreaProps extends TComponent {
    innerClassName?: string;
    value: string;
    defaultValue: string;
    showCount: boolean;
    maxLength: number;
    rows: number;
    placeholder: string;
    readOnly: boolean;
    disabled: boolean;
    autoSize?: boolean;
    /** 控制是否使用默认的推送功能 */
    useDefaultPush?: boolean;
    /** 控制是否使用监听键盘高度功能 */
    listenKeyboardHeight?: boolean;
    onChange: (value: string) => void;
    onBlur: (event: Event, element: HTMLTextAreaElement | null) => void;
    onFocus: (event: Event, element: HTMLTextAreaElement | null) => void;
    onClick?: (e: any) => void;
}

const defaultProps = {
    className: '',
    innerClassName: '',
    style: {},
    defaultValue: '',
    showCount: false,
    rows: 1,
    maxLength: 140,
    readOnly: false,
    disabled: false,
    autoSize: false
} as unknown as TextAreaProps;
const Textarea: ForwardRefRenderFunction<any, Partial<TextAreaProps>> = (props, ref) => {
    const {
        className,
        innerClassName,
        value,
        defaultValue,
        showCount,
        maxLength,
        rows,
        autoSize,
        placeholder,
        readOnly,
        disabled,
        style,
        onChange,
        onBlur,
        onFocus,
        onClick,
        ...rest
    } = { ...defaultProps, ...props };
    // textarea元素引用
    const textareaRef = useRef<HTMLTextAreaElement>(null);
    const compositionRef = useRef(false);
    const format = (value: string) => {
        if (maxLength !== -1 && value.length > maxLength) {
            return value.substring(0, maxLength);
        }
        return value;
    };

    const [inputValue, setInputValue] = usePropsValue<string>({
        value,
        defaultValue,
        finalValue: format(defaultValue),
        onChange
    });

    const setContentHeight = () => {
        const textarea: any = textareaRef.current;
        if (textarea) {
            textarea.style.height = 'auto';
            const height = textarea?.scrollHeight;
            if (height) {
                textarea.style.height = `${height}px`;
            }
        }
    };

    useEffect(() => {
        if (autoSize) setContentHeight();
    }, [autoSize, defaultValue, inputValue]);

    const handleChange = (event: any) => {
        const text = event.target;
        if (text) {
            const value = compositionRef.current ? text.value : format(text.value);
            setInputValue(value);
        } else {
            setInputValue('');
        }
    };

    const handleFocus = (event: Event) => {
        if (disabled) return;
        if (readOnly) return;
        onFocus && onFocus(event, textareaRef.current);
    };

    const handleBlur = (event: Event) => {
        if (disabled) return;
        if (readOnly) return;
        onBlur && onBlur(event, textareaRef.current);
    };

    useImperativeHandle(ref, () => ({
        clear: () => setInputValue(''),
        focus: () => textareaRef.current?.focus(),
        blur: () => textareaRef.current?.blur(),
        get nativeElement() {
            return textareaRef.current;
        }
    }));
    return (
        <div
            className={[$style.textarea, { [$style.disabled]: disabled }, className]}
            style={style}
            onClick={onClick}
        >
            <textarea
                ref={textareaRef}
                className={clsx([$style['textarea-inner'], innerClassName])}
                disabled={disabled || readOnly}
                readOnly={readOnly}
                onChange={handleChange}
                onCompositionEnd={() => {
                    compositionRef.current = false;
                }}
                onCompositionStart={() => {
                    compositionRef.current = true;
                }}
                value={inputValue}
                rows={rows}
                placeholder={placeholder ? placeholder : ''}
                onBlur={(e: any) => handleBlur(e)}
                onFocus={(e: any) => handleFocus(e)}
                maxLength={maxLength}
                {...rest}
            ></textarea>

            {showCount && (
                <div className={$style.limit}>
                    {inputValue.length}/{maxLength < 0 ? 0 : maxLength}
                </div>
            )}
        </div>
    );
};

Textarea.displayName = 'Textarea';
const KTextarea = forwardRef(Textarea);
export default KTextarea;
